package com.mz361.stdapi.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.mz361.common.utils.AesUtil;
import com.mz361.common.utils.RedisUtil;
import com.mz361.common.utils.StringUtil;
import com.mz361.component.payment.config.properties.PayMentProjectProperties;
import com.mz361.component.payment.service.PayMentService;
import com.mz361.modules.system.domain.*;
import com.mz361.modules.system.service.*;
import com.mz361.stdapi.domain.PayOrderResult;
import com.mz361.stdapi.domain.StandardData;
import com.mz361.stdapi.service.PayOrderResultService;
import com.mz361.stdapi.service.StandardProfileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 支付订单结果服务实现类
 * 处理支付订单的创建、状态查询及支付通知处理等核心功能
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PayOrderResultServiceImpl implements PayOrderResultService {

    private final PayMentService payMentService;
    private final CPackageService cPackageService;
    private final CMemberService cMemberService;
    private final PayOrderService payOrderService;
    private final OrderUserService orderUserService;
    private final PackageServiceService packageServiceService;
    private final ProductPackageService productPackageService;
    private final StandardProfileService standardProfileService;
    private final RedisUtil redisUtil;


    /**
     * 创建支付订单
     *
     * @param userId    用户ID
     * @param name      产品标识
     * @param amount    金额(预留参数，实际使用套餐价格)
     * @param payType   支付类型 0：微信支付 1：支付宝支付
     * @param orderType 订单类型 1：单个标准 2：套餐
     * @return 支付订单结果
     */
    @Override
    public PayOrderResult createPayOrder(String userId, String name, Integer amount,
                                         String payType, String orderType) {
        // 验证用户存在性
        CMember cMember = validateAndGetMember(userId);
        if (cMember == null) {
            log.warn("用户不存在，ID: {}", userId);
            return null;
        }

        // 生成订单ID
        String orderId = generateOrderId();

        // 计算订单价格信息
        OrderPriceInfo priceInfo = calculateOrderPrice(cMember, name, orderType);

        // 构建支付订单结果基础信息
        PayOrderResult result = buildBasePayOrderResult(orderId, priceInfo);

        // 获取支付二维码URL
        String codeUrl = getPaymentCodeUrl(orderId, priceInfo, payType);
        if (StringUtil.isEmpty(codeUrl)) {
            log.error("获取支付二维码失败，订单ID: {}", orderId);
            return result;
        } else {
            result.setCodeUrl(codeUrl);
        }

        // 缓存二维码URL
        cachePaymentCodeUrl(orderId, codeUrl);

        // 保存支付订单
        savePaymentOrder(orderId, cMember, payType, orderType, priceInfo);

        return result;
    }

    @Override
    public PayOrderResult refreshPaymentCode(String orderId) {
        // 查询订单信息
        PayOrder payOrder = payOrderService.getByOrderId(orderId);
        if (payOrder == null) {
            log.warn("订单不存在，订单ID: {}", orderId);
            return createEmptyPayOrderResult(orderId);
        }
        PayOrderResult result = new PayOrderResult();
        result.setOrderId(orderId);
        result.setAmount((double) payOrder.getTotalFee() / 100);
        result.setProductName(payOrder.getPaidPackageTag());
        result.setResultStatus(payOrder.getResultStatus());

        // 从缓存获取或重新生成二维码URL
        if (redisUtil.exists("PAYCODEURL:" + orderId)) {
            result.setCodeUrl(redisUtil.getValue("PAYCODEURL:" + orderId));
        } else {
            String codeUrl = generateNewPaymentCodeUrl(payOrder);
            cachePaymentCodeUrl(orderId, codeUrl);
            result.setCodeUrl(codeUrl);
        }

        return result;
    }

    @Override
    public PayOrderResult queryPaymentStatus(String orderId) {
        PayOrderResult result = createEmptyPayOrderResult(orderId);

        PayOrder payOrder = payOrderService.getByOrderId(orderId);
        if (payOrder != null) {
            result.setProductName(payOrder.getPaidPackageTag());
            result.setResultStatus(payOrder.getResultStatus());
            log.debug("查询订单状态成功，订单ID: {}, 状态: {}", orderId, payOrder.getResultStatus());
        } else {
            result.setResultStatus("PAYERROR");
            log.warn("订单不存在，订单ID: {}", orderId);
        }

        return result;
    }

    @Override
    public PayOrder processWeChatPaymentNotification(JSONObject jsonObject)
            throws IOException, GeneralSecurityException {
        try {
            // 解析微信支付通知
            JSONObject resource = jsonObject.getJSONObject("resource");
            String nonce = resource.getString("nonce");
            String ciphertext = resource.getString("ciphertext");
            String associatedData = resource.getString("associated_data");

            // 解密支付结果
            AesUtil aesUtil = new AesUtil(PayMentProjectProperties.apiV3Key
                    .getBytes(StandardCharsets.UTF_8));
            String decodeStr = aesUtil.decryptToString(
                    associatedData.getBytes(StandardCharsets.UTF_8),
                    nonce.getBytes(StandardCharsets.UTF_8),
                    ciphertext
            );

            JSONObject paymentResult = JSONObject.parseObject(decodeStr);
            String orderId = paymentResult.getString("out_trade_no");
            PayOrder payOrder = payOrderService.getByOrderId(orderId);

            if (payOrder == null) {
                log.error("微信支付通知，订单不存在: {}", orderId);
                return null;
            }

            // 更新订单信息
            updateOrderWithWeChatResult(payOrder, paymentResult);
            log.info("微信支付通知处理完成，订单ID: {}, 状态: {}", orderId, payOrder.getResultStatus());

            return payOrderService.save(payOrder);
        } catch (Exception e) {
            log.error("处理微信支付通知异常", e);
            throw e;
        }
    }

    @Override
    public PayOrder processAlipayPaymentNotification(HttpServletRequest request) throws Exception {
        try {
            // 获取请求参数
            Map<String, String> params = getRequestParameters(request);
            log.info("支付宝支付通知参数: {}", JSONObject.toJSONString(params));

            // 验证通知合法性
            boolean verified = payMentService.verifyNotify(params);
            if (!verified) {
                log.warn("支付宝支付通知验证失败");
                return null;
            }

            // 获取订单号
            String outTradeNo = new String(request.getParameter("out_trade_no")
                    .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            PayOrder payOrder = payOrderService.getByOrderId(outTradeNo);

            if (payOrder == null) {
                log.error("支付宝支付通知，订单不存在: {}", outTradeNo);
                return null;
            }

            // 更新订单信息
            updateOrderWithAlipayResult(payOrder, request);
            log.info("支付宝支付通知处理完成，订单ID: {}, 状态: {}", outTradeNo, payOrder.getResultStatus());

            return payOrderService.save(payOrder);
        } catch (Exception e) {
            log.error("处理支付宝支付通知异常", e);
            throw e;
        }
    }

    /**
     * 验证并获取用户信息
     */
    private CMember validateAndGetMember(String userId) {
        try {
            return cMemberService.getById(Long.valueOf(userId));
        } catch (NumberFormatException e) {
            log.error("用户ID格式错误: {}", userId, e);
            return null;
        }
    }

    /**
     * 生成订单ID
     */
    private String generateOrderId() {
        return StringUtil.getAutoEntry("MZ");
    }

    /**
     * 计算订单价格信息
     */
    private OrderPriceInfo calculateOrderPrice(CMember cMember, String name, String orderType) {
        double originalPrice;
        String productName;
        CSource cSource = cMember.getCsource();
        double discount = cSource != null ? cSource.getDiscount() / 100.0 : 1.0; // 渠道折扣

        if ("2".equals(orderType)) { // 购买套餐
            CPackage cPackage = cPackageService.getByCode(name);
            originalPrice = cPackage.getPrice();
            productName = cPackage.getClz();
        } else { // 单个标准购买
            StandardData standardData = standardProfileService.standardProfile(
                    cMember.getId().toString(), name);
            originalPrice = standardData.getPrice();
            productName = name;
        }

        double payAmount = Math.round(originalPrice * discount * 100 / 100);
        int activePayFen = (int) (payAmount * 100);
        return new OrderPriceInfo(activePayFen, payAmount, originalPrice, productName);
    }

    /**
     * 构建支付订单结果基础信息
     */
    private PayOrderResult buildBasePayOrderResult(String orderId, OrderPriceInfo priceInfo) {
        PayOrderResult result = new PayOrderResult();
        result.setOrderId(orderId);
        result.setAmount(priceInfo.getPayAmount());
        result.setProductName(priceInfo.getProductName());
        return result;
    }

    /**
     * 获取支付二维码URL
     */
    private String getPaymentCodeUrl(String orderId, OrderPriceInfo priceInfo, String payType) {
        return payMentService.getPayOrderCodeUrl(
                orderId, priceInfo.getActivePayFen(),
                priceInfo.getProductName(), Integer.valueOf(payType));
    }

    /**
     * 缓存支付二维码URL
     */
    private void cachePaymentCodeUrl(String orderId, String codeUrl) {
        redisUtil.setexValue("PAYCODEURL:" + orderId, 3600 * 2, codeUrl);
    }

    /**
     * 保存支付订单
     */
    private void savePaymentOrder(String orderId, CMember cMember,
                                  String payType, String orderType, OrderPriceInfo priceInfo) {
        PayOrder payOrder = findExistingUnfinishedOrder(cMember, orderType, priceInfo.getProductName());

        if (payOrder == null) { // 新建订单
            payOrder = createNewPaymentOrder(orderId, payType, cMember, orderType, priceInfo);
        } else { // 更新已有订单
            payOrder.setOrderId(orderId);
            updateExistingPaymentOrder(payOrder, payType);
        }
        payOrderService.save(payOrder);
        log.info("创建支付订单成功，订单ID: {}", orderId);
    }

    /**
     * 查找已有的未完成订单
     */
    private PayOrder findExistingUnfinishedOrder(CMember cMember,
                                                 String orderType, String productName) {
        if ("1".equals(orderType)) {
            return payOrderService.getByStandardNoAndMemeberIdNotSuccess(productName, cMember.getId());
        } else if ("2".equals(orderType)) {
            return payOrderService.findByCompanyAndPaidPackageTagNotSuccess(
                    productName, cMember.getCompanyId());
        }
        return null;
    }

    /**
     * 创建新的支付订单
     */
    private PayOrder createNewPaymentOrder(String orderId, String payType, CMember cMember,
                                           String orderType, OrderPriceInfo priceInfo) {
        PayOrder payOrder = new PayOrder();
        payOrder.setOrderId(orderId);
        payOrder.setMemeberId(cMember.getId());
        payOrder.setOrderType(orderType);
        payOrder.setInviteCode(cMember.getInviteCode() == null ? "" : cMember.getInviteCode());

        Company company = cMember.getCompany();
        if (company != null) {
            payOrder.setCompanyId(company.getId());
            payOrder.setCompanyName(company.getCompanyName());
            payOrder.setCreateBy(company.getCreateBy());
        }

        CSource cSource = cMember.getCsource();
        payOrder.setSourceKey(cSource != null ? cSource.getSourceKey() : null);
        payOrder.setPrice((long) priceInfo.getOriginalPrice() * 100);
        payOrder.setTotalFee((long) priceInfo.getPayAmount() * 100);
        payOrder.setPaidPackageTag(priceInfo.getProductName());
        payOrder.setPayType("1".equals(payType) ? "Alipay" : "WeChat");
        payOrder.setTradeType("NATIVE");
        payOrder.setResultStatus("NOTPAY");
        payOrder.setInvoiceStatus("0");
        payOrder.setCreateDate(new Date());
        payOrder.setUpdateDate(new Date());

        return payOrder;
    }

    /**
     * 更新已有支付订单
     */
    private void updateExistingPaymentOrder(PayOrder payOrder, String payType) {
        payOrder.setPayType(payType.equals("1") ? "Alipay" : "WeChat");
        payOrder.setOrderId(payOrder.getOrderId() != null ? payOrder.getOrderId() : generateOrderId());
        payOrder.setUpdateDate(new Date());
    }

    /**
     * 生成新的支付二维码URL
     */
    private String generateNewPaymentCodeUrl(PayOrder payOrder) {
        String payType = payOrder.getPayType().equals("Alipay") ? "1" : "0";
        return payMentService.getPayOrderCodeUrl(
                payOrder.getOrderId(), payOrder.getTotalFee().intValue(),
                payOrder.getPaidPackageTag(), Integer.valueOf(payType));
    }

    /**
     * 创建空的支付订单结果
     */
    private PayOrderResult createEmptyPayOrderResult(String orderId) {
        PayOrderResult result = new PayOrderResult();
        result.setOrderId(orderId);
        return result;
    }

    /**
     * 从微信支付结果更新订单信息
     */
    private void updateOrderWithWeChatResult(PayOrder payOrder, JSONObject paymentResult) {
        String resultStatus = paymentResult.getString("trade_state");
        payOrder.setResultStatus(resultStatus);
        payOrder.setPayType("WeChat");
        payOrder.setTotalFee(paymentResult.getJSONObject("amount").getLong("total"));
        payOrder.setOpenid(paymentResult.getJSONObject("payer").getString("openid"));
        payOrder.setTransactionId(paymentResult.getString("transaction_id"));
        payOrder.setReturnData(paymentResult.toJSONString());
        payOrder.setUpdateDate(new Date());

        if ("SUCCESS".equals(resultStatus)) {
            handleSuccessfulPayment(payOrder);
        }
    }

    /**
     * 从支付宝支付结果更新订单信息
     */
    private void updateOrderWithAlipayResult(PayOrder payOrder, HttpServletRequest request) {
        String tradeNo = new String(request.getParameter("trade_no")
                .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        String tradeStatus = new String(request.getParameter("trade_status")
                .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        String totalAmount = new String(request.getParameter("total_amount")
                .getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

        payOrder.setTotalFee((long) (Double.parseDouble(totalAmount) * 100));
        payOrder.setPayType("Alipay");
        payOrder.setTransactionId(tradeNo);
        payOrder.setUpdateDate(new Date());

        if ("TRADE_SUCCESS".equals(tradeStatus)) {
            payOrder.setResultStatus("SUCCESS");
            handleSuccessfulPayment(payOrder);
        } else if ("TRADE_FINISHED".equals(tradeStatus)) {
            payOrder.setResultStatus("CLOSED");
        }
    }

    /**
     * 处理支付成功的业务逻辑
     */
    private void handleSuccessfulPayment(PayOrder payOrder) {
        CMember cMember = cMemberService.getById(payOrder.getMemeberId());
        if (cMember != null) {
            if ("2".equals(payOrder.getOrderType())) { // 套餐订单
                CPackage cPackage = cPackageService.getByCode(payOrder.getPaidPackageTag());
                ProductPackage productPackage = productPackageService.getByPackageId(cPackage.getId());
                Product product = productPackage.getProduct();
                saveMemberOrderUser(cMember, cPackage, product);
            } else if ("1".equals(payOrder.getOrderType())) { // 产品订单
                cacheStandardAccessPermissions(cMember, payOrder.getPaidPackageTag());
            }
        }
    }

    /**
     * 保存个人用户套餐服务信息
     */
    private void saveMemberOrderUser(CMember cMember, CPackage cPackage, Product product) {
        List<OrderUser> existingUsers = orderUserService.getOrderUsersByMemeberIdAndPackageId(
                cMember.getId(), cPackage.getId());
        List<PackageService> packageServices = packageServiceService.getPackageServiceByPackageId(cPackage.getId());

        List<OrderUser> usersToSave = packageServices.stream()
                .map(service -> findOrCreateMemberOrderUser(existingUsers, cMember, cPackage, product, service))
                .peek(user -> clearZeroCountCache("1".equals(cMember.getType()) ? "P:" + cMember.getId() : "Q:" + cMember.getCompanyId(), user.getServiceName()))
                .collect(Collectors.toList());

        if (!usersToSave.isEmpty()) {
            orderUserService.saveAll(usersToSave);
            if ("1".equals(cMember.getType())) {
                log.info("保存个人用户套餐服务信息成功，用户: {}, 套餐: {}", cMember.getName(), cPackage.getName());
            } else {
                log.info("保存企业用户套餐服务信息成功，公司: {}, 套餐: {}", cMember.getCompanyName(), cPackage.getName());
            }
        }
    }

    /**
     * 查找或创建个人订单用户
     */
    private OrderUser findOrCreateMemberOrderUser(List<OrderUser> existingUsers, CMember cMember,
                                                  CPackage cPackage, Product product, PackageService packageService) {
        if (existingUsers != null) {
            for (OrderUser user : existingUsers) {
                if (packageService.getService().getName().equals(user.getServiceName())) {
                    user.setQuantity(user.getQuantity() + packageService.getQuantity());
                    user.setUpdateDate(new Date());
                    return user;
                }
            }
        }

        OrderUser newUser = new OrderUser();
        if ("1".equals(cMember.getType())) {//个人用户
            newUser.setMemeberId(cMember.getId());
            newUser.setMemeberName(cMember.getName());
        } else {//企业用户
            newUser.setCompanyId(cMember.getCompanyId());
            newUser.setCompanyName(cMember.getCompanyName());
        }

        newUser.setPackageId(cPackage.getId());
        newUser.setPackageName(cPackage.getName());
        newUser.setProductId(product.getId());
        newUser.setProductName(product.getName());
        newUser.setServiceId(packageService.getServiceId());
        newUser.setServiceName(packageService.getService().getName());
        newUser.setUnit(packageService.getUnit());
        newUser.setQuantity(packageService.getQuantity());
        newUser.setCreateDate(new Date());
        newUser.setUpdateDate(new Date());
        newUser.setStatus((byte) 1);

        return newUser;
    }

    /**
     * 缓存标准访问权限
     */
    private void cacheStandardAccessPermissions(CMember cMember, String standardCode) {
        redisUtil.hSet("STANDARDINFO:READONLINE:MZUNI",
                cMember.getId() + "|" + standardCode, standardCode);
        redisUtil.hSet("STANDARDINFO:DOWNLOAD:MZUNI",
                cMember.getId() + "|" + standardCode, standardCode);
    }

    /**
     * 清除套餐次数为零的缓存标识
     */
    private void clearZeroCountCache(String key, String serviceName) {
        String cacheKey = getZeroCountCacheKey(serviceName);
        redisUtil.hDel(cacheKey, key);
        log.debug("清除缓存: {}: {}", cacheKey, key);
    }

    /**
     * 获取次数为零的缓存键
     */
    private String getZeroCountCacheKey(String serviceName) {
        switch (serviceName) {
            case "打印":
                return "PRINT:ZERO";
            case "下载":
                return "DOWNLOAD:ZERO";
            default:
                return "READ:ZERO";
        }
    }

    /**
     * 获取HTTP请求参数
     */
    private Map<String, String> getRequestParameters(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();

        for (Object nameObj : requestParams.keySet()) {
            String name = (String) nameObj;
            String[] values = (String[]) requestParams.get(name);
            String valueStr = String.join(",", values);
            params.put(name, valueStr);
        }

        return params;
    }

    /**
     * 订单价格信息封装类
     */
    private static class OrderPriceInfo {
        private final int activePayFen;
        private final double payAmount;
        private final double originalPrice;
        private final String productName;

        public OrderPriceInfo(int activePayFen, double payAmount, double originalPrice, String productName) {
            this.activePayFen = activePayFen;
            this.payAmount = payAmount;
            this.originalPrice = originalPrice;
            this.productName = productName;
        }

        public int getActivePayFen() {
            return activePayFen;
        }

        public double getPayAmount() {
            return payAmount;
        }

        public double getOriginalPrice() {
            return originalPrice;
        }

        public String getProductName() {
            return productName;
        }
    }
}